// 联合类型 和类型收缩
function greet(person: string | string[]): string | string[] {
  if (typeof person === 'string') {
    return `你好呀我是${person}返回了`
  } else if (Array.isArray(person)) {
    return `哈哈哈${person}`
  }
  throw new Error('this is error');
}

// .交叉运算符特性
type PonitA = {
  x: string;
  y: number;
};

type PointB = {
  name: string;
};
type PointC = PointB & PonitA; //{x: string;y:number;name:string}

// 复杂类型的交叉运算
type D = {
  d: boolean;
}
type E = {
  e: string;
}
type F = {
  f: number;
}

type Test1 = {
  x: D
}
type Test2 = {
  x: E
}
type Test3 = {
  x: F
}

type Test4 = Test1 & Test2 & Test3;// {x:{d: boolean;e: string;f:number}}

// 简单类型的交叉运算
type Foo = {
  name: string;
  age: number,
  color: boolean;// 注意：这里boolean可以视作由true｜false两个字面量的联合类型
};
type Boo = {
  name: boolean;
  age: number,
  color: string
};
type Fb = Foo & Boo;// never



// 函数类型的交叉运算
type F1 = (x: string, y: string) => void;
type F2 = (x: number, y: number) => void;
type F3 = F1 & F2;// (x: string | number, y: number | string) => void;
let fn: F3 = (x: string | number, y: number | string) => { };
fn('helo', 'word');//正确
//fn('helo', 1);//错误
fn(1, 2);//正确
//fn(3, 'word');//错误

// 如果希望以上错误修复可以这样
type F4 = (x: string, y: number) => void;
type F5 = (x: number, y: string) => void;
let fn2: F1 & F2 & F4 & F5 = (x: string | number, y: string | number) => { };
fn2('hello', 1);//正确
fn2(1, '222');//正确


// PartialByKeys
//工具类型
type PartialByKeys<T, U extends keyof T> = {
  [K in U]?: T[K]
} & Pick<T, Exclude<keyof T, U>>;

type U1 = {
  name: string;
  age: number;
  choose: boolean;
};

type U2 = PartialByKeys<U1, 'name'>;// {name?: string;age:number;choose: boolean};
let user: U2 = {
  age: 11,
  choose: true
};//正确


// 显式指定泛型
function foo1<T, R>(x: T, y: R) { }
foo1<string, number>('111', 2); // function foo1<string, number>(x: string, y: number): void
// 隐式指定泛型
foo1(22, '111')// function foo1<number, string>(x: number, y: string): void